﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufTable.h"
#include "GnufQtItem.h"
#include <QtWidgets/QTableWidget>
#include <QtCore/QPointer>

class QLabel;
class QTableWidgetItem;

namespace gnuf {

    class Table;
    class TableRow;
    class QtTable;

    class QtTableRowHeader final : public QWidget
    {
        Q_OBJECT
    public:
        explicit QtTableRowHeader(QtTableRow *);
        virtual ~QtTableRowHeader();
        QtTableRow * qtTableRow() const { return m_qtTableRow; }
        void adjustStyleSheet(TableRow *);
        void refreshIcon(TableRow *);
    protected:
        // Inherits from QWidget...
        void mousePressEvent(QMouseEvent *) override;
        void paintEvent(QPaintEvent *) override;
    private:
        QPointer<QtTableRow> m_qtTableRow;
        QLabel * m_qtIcon;
        QLabel * m_qtLabel;
        QWidget * m_qtButtonList;
    };

    class QtTableRow final : public QtItemWith<QObject, TableRow>
    {
    public:
        explicit QtTableRow(TableRow *, QtTable *);
        virtual ~QtTableRow();

        virtual void refresh(EWhatDirty) override {}

        // Return the internal row index.
        inline int internalRowIndex() const { return m_internalRowIndex; }

        // Return the external row index.
        int externalRowIndex() const;

        // Set/Get the visible.
        void refreshVisibility();

        // Respond to the selection change.
        void onSelectionChanged();

        // Dump the cells except for the header.
        // Note that need to call clearCells() before call this method.
        void dumpCells();

        // Clear the cells except for the header.
        void clearCells();

        // insert a cell
        void setCell(int idx, Item* pItem);

        // 1st column is the header. So, dump the cells from 2nd column.
        // See aslo, QtTableRow::dumpContentsAt(int internalRowIndex).
        inline int cellStartIndex() const { return 1; }

        void refreshExpansionIcon();

        void refreshInternalNameForJournal(int idx);
        
    private:
        friend class QtTable;
        void setInternalRowIndex(int);
        void dumpContents();
        bool needToDump() const;

        QtTable * m_qtTable;
        int m_internalRowIndex;
        bool m_cellsDumped;
        QtTableRowHeader * m_qtHeader;
        std::list<QtItem *> m_qtCells;
    };

    class GNUF_BASE_EXPORT QtTable final
        : public QtItemWith<QTableWidget, Table>
    {
        Q_OBJECT
    public:
        explicit QtTable(Table *, bool wantToDumpCellsAsDemand = true);
        virtual ~QtTable();

        bool wantToDumpCellsAsDemand() const {
            return m_wantToDumpCellsAsDemand;
        }

        // Return the row count.
        int headerRowCount() const;
        
        // Add a table row.
        bool addQtTableRow(QtTableRow *);

        // Insert a table row
        bool insertQtTableRow(QtTableRow*, int idx = -1);

        // Remove a Table row
        bool removeQtTableRow(const QtTableRow*);

        void setEmptyItem(const QtTableRow * qtRow, int column);
        void unsetEmptyItem(const QtTableRow * qtRow, int column);
        void setWidget(const QtTableRow * qtRow, int column, QWidget *);
        void unsetWidget(const QtTableRow * qtRow, int column);
        bool isCellBlank(const QtTableRow * qtRow, int column) const;
        void setRowVisible(const QtTableRow * qtRow, bool visible);
        void setRowSelected(const QtTableRow * qtRow, bool selected);
        void setColumnVisible(const int columnIndex, bool visible);

        void adjustRowHeightAt(int index, int height);
        int rowHeightAt(int index) const;

        virtual void refresh(EWhatDirty) override {}

        void dumpCellsAsDemand();

    protected:
        // Inherits from QWidget...
        void showEvent(QShowEvent *) override;
        void resizeEvent(QResizeEvent *) override;
        void mousePressEvent(QMouseEvent *) override;

    private slots:
        void onTriggerDumpingCellsAsDemand(int);
        
    private:
        void initializeHeader();
        void initializeBody();
        void updateHeaderGeometry();
        // 当placeHolder==false的时候，创建空的单元格，而不是真实的。
        // 否则，当单元格有用户自定义的内容时，重复创建QItem会导致异常。
        void dumpHeader(QTableWidget *, bool placeHolder = false);
        void dumpContents();
        void clearContents();
        void adjustRowHeightAndColumnWidth(QTableWidget *);
        void setHeaderDataForJournal(QTableWidget *, bool bTableHeader);

        QTableWidget * m_qtTableHeader;
        const bool m_wantToDumpCellsAsDemand;
        std::list<QtTableRow*> m_qtTableRows;
    };

}
